#include "gtest/gtest.h"
#include "spdlog/spdlog.h"
#include "thread_manage.h"
#include "mock/task_queue_mock.cpp"
#include "task_queue.h"

TEST(thread_manage_test, base) {
    std::function<void()> run = [] {
        spdlog::info("thread_manage_test.base");
        std::this_thread::sleep_for(std::chrono::milliseconds(200));
    };

    simpleThread::ThreadManage threadManage(2, 2);
    threadManage.submit(run);
    threadManage.submit(run);
    threadManage.submit(run);
    threadManage.initThreads();

    EXPECT_EQ(threadManage.getMaxSize(), 2);
    EXPECT_EQ(threadManage.getCoreSize(), 2);
}

TEST(thread_manage_test, join) {
    std::function<void()> run = [] {
        spdlog::info("thread_manage_test.join");
        std::this_thread::sleep_for(std::chrono::milliseconds(200));
    };

    simpleThread::ThreadManage threadManage;
    threadManage.initThreads();
    for (int i = 0; i < std::thread::hardware_concurrency(); ++i) {
        threadManage.submit(run);
    }

    EXPECT_EQ(threadManage.getTotal(), std::thread::hardware_concurrency());
    threadManage.join();
    EXPECT_EQ(threadManage.getTotal(), 0);
}

TEST(thread_manage_test, shutdown) {
    std::function<void()> run = [] {
        spdlog::info("thread_manage_test.shutdown");
        std::this_thread::sleep_for(std::chrono::milliseconds(200));
    };

    simpleThread::ThreadManage threadManage(3, 10);
    for (int i = 0; i < 100; ++i) {
        threadManage.submit(run);
    }

    EXPECT_EQ(threadManage.getTotal(), 10);
    threadManage.shutdown();
    EXPECT_EQ(threadManage.getTotal(), 0);
}

TEST(thread_manage_test, close) {
    std::function<void()> run = [] {
        spdlog::info("thread_manage_test.shutdown");
        std::this_thread::sleep_for(std::chrono::milliseconds(200));
    };

    simpleThread::ThreadManage threadManage(3, 10);
    threadManage.initThreads();
    for (int i = 0; i < 100; ++i) {
        threadManage.submit(run);
    }

    EXPECT_EQ(threadManage.getTotal(), 10);
    threadManage.shutdown();
    EXPECT_EQ(threadManage.getTotal(), 0);
    threadManage.submit(run);
}

TEST(thread_manage_test, removeThread) {
    std::function<void()> run = [] {
        std::this_thread::sleep_for(std::chrono::milliseconds(100));
    };

    simpleThread::ThreadManage threadManage(3, 10);
    threadManage.setIdleTime(1);
    for (int i = 0; i < 10; ++i) {
        threadManage.submit(run);
    }
    threadManage.initThreads();

    EXPECT_EQ(threadManage.getTotal(), 10);
    std::this_thread::sleep_for(std::chrono::seconds(3));
    EXPECT_EQ(threadManage.getTotal(), 3);
    threadManage.shutdown();
    EXPECT_EQ(threadManage.getTotal(), 0);
}